home *** CD-ROM | disk | FTP | other *** search
/ PD Collection CD 1 / PD Collection CD 1.iso / textual / tex / files / !tex / TeXsource / commontex / c / boxlists < prev    next >
Encoding:
Text File  |  1988-04-18  |  32.3 KB  |  1,127 lines

  1. /*
  2.  *    Copyright 1986, 1987 Pat Joseph Monardo. All rights reserved.
  3.  *    Copying of this file is granted according to the provisions 
  4.  *    specified in the file COPYING which must accompany this file.
  5.  */
  6.  
  7.  
  8. /*
  9.  *              boxlists.c
  10.  */
  11.  
  12. #include "tex.h"
  13. #include "cmds.h"
  14. #include "heap.h"
  15. #include "eq.h"
  16. #include "eqstack.h"
  17. #include "def.h"
  18. #include "box.h"
  19. #include "tokenstack.h"
  20. #include "token.h"
  21. #include "scan.h"
  22. #include "tokenlists.h"
  23. #include "evalstack.h"
  24. #include "tfm.h"
  25. #include "pack.h"
  26. #include "page.h"
  27. #include "math.h"
  28. #include "io.h"
  29. #include "print.h"
  30. #include "error.h"
  31. #include "boxlists.h"
  32.  
  33. ptr             cur_box;
  34.  
  35. append_glue ()
  36. {
  37.         hword   s;
  38.         
  39.         s = cur_chr;
  40.         switch (s) 
  41.         {
  42.         case FIL_CODE:
  43.                 cur_val = fil_glue;
  44.                 break;
  45.  
  46.         case FILL_CODE:
  47.                 cur_val = fill_glue;
  48.                 break;
  49.  
  50.         case SS_CODE:
  51.                 cur_val = ss_glue;
  52.                 break;
  53.  
  54.         case FIL_NEG_CODE:
  55.                 cur_val = fil_neg_glue;
  56.                 break;
  57.  
  58.         case SKIP_CODE:
  59.                 scan_glue(GLUE_VAL);
  60.                 break;
  61.  
  62.         case MSKIP_CODE:
  63.                 scan_glue(MU_VAL);
  64.                 break;
  65.  
  66.         default:
  67.                 break;
  68.         }
  69.         tail_append(new_glue((ptr) cur_val));
  70.         if (s >= SKIP_CODE) {
  71.                 decr(glue_ref_count((ptr) cur_val));
  72.                 if (s > SKIP_CODE)
  73.                         subtype(tail) = MU_GLUE;
  74.         }
  75. }
  76.  
  77. append_kern ()
  78. {
  79.         qword   s;
  80.         
  81.         s = cur_chr;
  82.         scan_dimen(s == MU_GLUE, FALSE, FALSE);
  83.         tail_append(new_kern(cur_val));
  84.         subtype(tail) = s;
  85. }
  86.  
  87. handle_right_brace ()
  88. {
  89.         scal    d;
  90.         val             f;
  91.         ptr             p;
  92.         ptr             q;
  93.         
  94.         switch (cur_group)
  95.         {
  96.         case SIMPLE_GROUP:
  97.                 unsave();
  98.                 break;
  99.         
  100.         case BOTTOM_LEVEL:
  101.                 print_err("Too many }'s");
  102.                 help_close_group();
  103.                 error();
  104.                 break;
  105.         
  106.         case SEMI_SIMPLE_GROUP:
  107.         case MATH_SHIFT_GROUP:
  108.         case MATH_LEFT_GROUP:
  109.                 extra_right_brace();
  110.                 break;
  111.  
  112.         case HBOX_GROUP:
  113.                 package(0);
  114.                 break;
  115.         
  116.         case ADJUSTED_HBOX_GROUP:
  117.                 adjust_tail = adjust_head;
  118.                 package(0);
  119.                 break;
  120.         
  121.         case VBOX_GROUP:
  122.                 end_graf();
  123.                 package(0);
  124.                 break;
  125.         
  126.         case VTOP_GROUP:
  127.                 end_graf();
  128.                 package(VTOP_CODE);
  129.                 break;
  130.  
  131.         case INSERT_GROUP:
  132.                 end_graf();
  133.                 q = split_top_skip;
  134.                 add_glue_ref(q);
  135.                 d = split_max_depth;
  136.                 f = floating_penalty;
  137.                 unsave();
  138.                 decr(save_ptr);
  139.                 p = vpack(link(head), NATURAL);
  140.                 pop_nest();
  141.                 if (saved(0) < 255) {
  142.                         tail_append(get_node(INS_NODE_SIZE));
  143.                         type(tail) = INS_NODE;
  144.                         subtype(tail) = qi(saved(0));
  145.                         height(tail) = height(p) + depth(p);
  146.                         ins_ptr(tail) = list_ptr(p);
  147.                         split_top_ptr(tail) = q;
  148.                         depth(tail) = d;
  149.                         float_cost(tail) = f;
  150.                 } else {
  151.                         tail_append(get_node(SMALL_NODE_SIZE));
  152.                         type(tail) = ADJUST_NODE;
  153.                         subtype(tail) = 0;
  154.                         adjust_ptr(tail) = list_ptr(p);
  155.                         delete_glue_ref(q);
  156.                 }
  157.                 free_node(p, BOX_NODE_SIZE);
  158.                 if (nest_ptr == 0) 
  159.                         build_page();
  160.                 break;
  161.         
  162.         case OUTPUT_GROUP:
  163.                 if (loc != NULL)  {
  164.                         print_err("Unbalanced output routine");
  165.                         help_output_balance();
  166.                         error();
  167.                         do get_token();
  168.                         while (loc != NULL);
  169.                 }
  170.                 end_token_list();
  171.                 end_graf();
  172.                 unsave();
  173.                 output_active = FALSE;
  174.                 insert_penalties = 0;
  175.                 if (box(255) != NULL) {
  176.                         print_err("Output routine didn't use all of ");
  177.                         print_esc("box255");
  178.                         help_output();
  179.                         box_error(255);
  180.                 }
  181.                 if (tail != head) {
  182.                         link(page_tail) = link(head);
  183.                         page_tail = tail;
  184.                 }
  185.                 if (link(page_head) != NULL) {
  186.                         if (link(contrib_head) == NULL)
  187.                                 contrib_tail = page_tail;
  188.                         link(page_tail) = link(contrib_head);
  189.                         link(contrib_head) = link(page_head);
  190.                         link(page_head) = NULL;
  191.                         page_tail = page_head;
  192.                 }
  193.                 pop_nest();
  194.                 build_page();
  195.                 break;
  196.         
  197.         case DISC_GROUP:
  198.                 build_discretionary();
  199.                 break;
  200.         
  201.         case ALIGN_GROUP:
  202.                 back_input();
  203.                 cur_tok = CS_TOKEN_FLAG + FROZEN_CR;
  204.                 print_err("Missing ");
  205.                 print_esc("cr");
  206.                 print(" inserted");
  207.                 help_align_cr();
  208.                 ins_error(); 
  209.                 break;
  210.  
  211.         case NO_ALIGN_GROUP:
  212.                 end_graf();
  213.                 unsave();
  214.                 align_peek();
  215.                 break;
  216.         
  217.         case VCENTER_GROUP:
  218.                 end_graf();
  219.                 unsave();
  220.                 save_ptr -= 2;
  221.                 p = vpackage(link(head), saved(1), (int) saved(0), MAX_DIMEN);
  222.                 pop_nest();
  223.                 tail_append(new_noad());
  224.                 type(tail) = VCENTER_NOAD;
  225.                 math_type(nucleus(tail)) = SUB_BOX;
  226.                 info(nucleus(tail)) = p;
  227.                 break;
  228.         
  229.         case MATH_CHOICE_GROUP:
  230.                 build_choices();
  231.                 break;
  232.  
  233.         case MATH_GROUP:
  234.                 unsave();
  235.                 decr(save_ptr);
  236.                 math_type(saved(0)) = SUB_MLIST;
  237.                 p = fin_mlist(NULL);
  238.                 info(saved(0)) = p;
  239.                 if (p != NULL) {
  240.                         if (link(p) == NULL) {
  241.                                 if (type(p) == ORD_NOAD) {
  242.                                         if (math_type(subscr(p)) == EMPTY &&
  243.                                                 math_type(supscr(p)) == EMPTY) {
  244.                                                 mem[saved(0)].hh = mem[nucleus(p)].hh;
  245.                                                 free_node(p, NOAD_SIZE);
  246.                                         }
  247.                                 } else if (type(p) == ACCENT_NOAD &&
  248.                                         saved(0) == nucleus(tail) &&
  249.                                         type(tail) == ORD_NOAD) {
  250.                                         q = head;
  251.                                         while (link(q) != tail)
  252.                                                 q = link(q);
  253.                                         link(q) = p;
  254.                                         free_node(tail, NOAD_SIZE);
  255.                                         tail = p;
  256.                                 }
  257.                         }
  258.                 }
  259.                 break;
  260.         
  261.         default:
  262.                 confusion("rightbrace");
  263.                 break;
  264.         }
  265. }
  266.  
  267. extra_right_brace ()
  268. {
  269.         print_err("Extra }, or forgotten ");
  270.         switch (cur_group) 
  271.         {
  272.         case SEMI_SIMPLE_GROUP:
  273.                 print_esc("endgroup");
  274.                 break;
  275.  
  276.         case MATH_SHIFT_GROUP:
  277.                 print_char('$');
  278.                 break;
  279.  
  280.         case MATH_LEFT_GROUP:
  281.                 print_esc("right");
  282.                 break;
  283.         }
  284.         help_group_close();
  285.         error();
  286.         incr(align_state);
  287. }
  288.  
  289. package (c)
  290.         int             c;
  291. {
  292.         scal    d;
  293.         scal    h;
  294.         ptr             p;
  295.  
  296.         d = box_max_depth;
  297.         unsave();
  298.         save_ptr -= 3;
  299.         if (mode == -HMODE)
  300.                 cur_box = hpack(link(head), saved(2), (int) saved(1));
  301.         else {
  302.                 cur_box = vpackage(link(head), saved(2), (int) saved(1), d);
  303.                 if (c == VTOP_CODE) {
  304.                         h = 0;
  305.                         p = list_ptr(cur_box);
  306.                         if (p != NULL && type(p) <= RULE_NODE)
  307.                                 h = height(p);
  308.                         depth(cur_box) += height(cur_box) - h;
  309.                         height(cur_box) = h;
  310.                 }
  311.         }
  312.         pop_nest();
  313.         box_end();
  314. }
  315.  
  316. box_end ()
  317. {
  318.         ptr             p;
  319.  
  320.         if (saved(0) < BOX_FLAG) {
  321.                 if (cur_box != NULL) {
  322.                         shift_amount(cur_box) = saved(0);
  323.                         if (abs(mode) == VMODE) {
  324.                                 append_to_vlist(cur_box);
  325.                                 if (adjust_tail != NULL) {
  326.                                         if (adjust_head != adjust_tail) {
  327.                                                 link(tail) = link(adjust_head);
  328.                                                 tail = adjust_tail;
  329.                                         }
  330.                                         adjust_tail = NULL;
  331.                                 }
  332.                                 if (mode > 0) 
  333.                                         build_page();
  334.                         } else {
  335.                                 if (abs(mode) == HMODE)
  336.                                         space_factor = 1000;
  337.                                 else {
  338.                                         p = new_noad();
  339.                                         math_type(nucleus(p)) = SUB_BOX;
  340.                                         info(nucleus(p)) = cur_box;
  341.                                         cur_box = p;
  342.                                 }
  343.                                 link(tail) = cur_box;
  344.                                 tail = cur_box;
  345.                         }
  346.                 }
  347.         } else if (saved(0) < SHIP_OUT_FLAG)
  348.                 if (saved(0) < BOX_FLAG + 256)
  349.                         eq_define((ptr)(BOX_BASE-BOX_FLAG+saved(0)), BOX_REF, cur_box);
  350.                 else
  351.                         geq_define((ptr)(BOX_BASE-BOX_FLAG-256+saved(0)), BOX_REF, cur_box);
  352.         else if (cur_box != NULL) {
  353.                 if (saved(0) > SHIP_OUT_FLAG) {
  354.                         get_nbrx_token();
  355.                         if (cur_cmd == HSKIP && abs(mode) != VMODE ||
  356.                                 cur_cmd == VSKIP && abs(mode) == VMODE ||
  357.                                 cur_cmd == MSKIP && abs(mode) == MMODE) {
  358.                                 append_glue();
  359.                                 leader_ptr(tail) = cur_box;
  360.                                 subtype(tail) = saved(0) - (LEADER_FLAG - A_LEADERS);
  361.                         } else {
  362.                                 print_err("Leaders not followed by proper glue");
  363.                                 help_leaders();
  364.                                 back_error();
  365.                                 flush_node_list(cur_box);
  366.                         }
  367.                 } else
  368.                         ship_out(cur_box);
  369.         }
  370. }
  371.  
  372. begin_box ()
  373. {
  374.         int             k;
  375.         int             m;
  376.         int             n;
  377.         ptr             p;
  378.         ptr             q;
  379.  
  380.         switch (cur_chr)
  381.         {
  382.         case BOX_CODE:
  383.                 scan_eight_bit_int();
  384.                 cur_box = box(cur_val);
  385.                 box(cur_val) = NULL;
  386.                 break;
  387.         
  388.         case COPY_CODE:
  389.                 scan_eight_bit_int();
  390.                 cur_box = copy_node_list(box(cur_val));
  391.                 break;
  392.         
  393.         case LAST_BOX_CODE:
  394.                 cur_box = NULL;
  395.                 if (abs(mode) == MMODE) {
  396.                         you_cant();
  397.                         help_lastbox_m();
  398.                         error();
  399.                 } else if (mode == VMODE && head == tail) {
  400.                         you_cant();
  401.                         help_lastbox_v();
  402.                         error();
  403.                 } else if (!is_char_node(tail) &&
  404.                         (type(tail) == HLIST_NODE || type(tail) == VLIST_NODE)) {
  405.                         q = head;
  406.                         do      {
  407.                                 p = q;
  408.                                 if (!is_char_node(q) && type(q) == DISC_NODE) {
  409.                                         for (m = 1; m <= replace_count(q); incr(m)) 
  410.                                                 p = link(p);
  411.                                         if (p == tail)
  412.                                                 break;
  413.                                 }
  414.                                 q = link(p);
  415.                         } while (q != tail);
  416.                         cur_box = tail;
  417.                         shift_amount(cur_box) = 0;
  418.                         tail = p;
  419.                         link(p) = NULL;
  420.                 }
  421.                 break;
  422.  
  423.         case VSPLIT_CODE:
  424.                 scan_eight_bit_int();
  425.                 n = cur_val;
  426.                 if (!scan_keyword("to")) {
  427.                         print_err("Missing `to' inserted");
  428.                         help_vsplit();
  429.                         error();
  430.                 }
  431.                 scan_normal_dimen();
  432.                 cur_box = vsplit(n, cur_val);
  433.                 break;
  434.         
  435.         default:
  436.                 k = cur_chr - VTOP_CODE;
  437.                 incr(save_ptr);
  438.                 scan_spec();
  439.                 if (k == HMODE) {
  440.                         if (saved(-3) < BOX_FLAG && abs(mode) == VMODE)
  441.                                 new_save_level(ADJUSTED_HBOX_GROUP);
  442.                         else new_save_level(HBOX_GROUP);
  443.                 } else {
  444.                         if (k == VMODE)
  445.                                 new_save_level(VBOX_GROUP);
  446.                         else {
  447.                                 new_save_level(VTOP_GROUP);
  448.                                 k = VMODE;
  449.                         }
  450.                         normal_paragraph();
  451.                 }
  452.                 push_nest();
  453.                 mode = -k;
  454.                 if (k == VMODE) {
  455.                         prev_depth = IGNORE_DEPTH;
  456.                         if (every_vbox != NULL)
  457.                                 begin_token_list(every_vbox, EVERY_VBOX_TEXT);
  458.                 } else {
  459.                         space_factor = 1000;
  460.                         if (every_hbox != NULL) 
  461.                                 begin_token_list(every_hbox, EVERY_HBOX_TEXT);
  462.                 }
  463.                 return;
  464.                 break;
  465.         }
  466.         box_end();
  467. }
  468.  
  469. scan_spec ()
  470. {
  471.         if (scan_keyword("to"))
  472.                 saved(0) = EXACTLY;
  473.         else if (scan_keyword("spread")) 
  474.                 saved(0) = ADDITIONAL;
  475.         else {
  476.                 saved(0) = ADDITIONAL;
  477.                 saved(1) = 0;
  478.                 goto found;
  479.         }
  480.         scan_normal_dimen();
  481.         saved(1) = cur_val;
  482.  
  483. found:
  484.         save_ptr += 2;
  485.         scan_left_brace();
  486. }
  487.  
  488. scan_box ()
  489. {
  490.         get_nbrx_token();
  491.         if (cur_cmd == MAKE_BOX)
  492.                 begin_box();
  493.         else if (saved(0) >= LEADER_FLAG &&
  494.                         (cur_cmd == HRULE || cur_cmd == VRULE)) {
  495.                         cur_box = scan_rule_spec();
  496.                         box_end();
  497.         } else {
  498.                 print_err("A <box> was supposed to be here");
  499.                 help_box();
  500.                 back_error();
  501.         }
  502. }
  503.  
  504. normal_paragraph ()
  505. {
  506.         if (looseness != 0)
  507.                 eq_word_define((ptr) INT_BASE + LOOSENESS_CODE, 0L);
  508.         if (hang_indent != 0)
  509.                 eq_word_define((ptr) DIMEN_BASE + HANG_INDENT_CODE, 0L);
  510.         if (hang_after != 1)
  511.                 eq_word_define((ptr) INT_BASE + HANG_AFTER_CODE, 1L);
  512.         if (par_shape_ptr != NULL)
  513.                 eq_define(PAR_SHAPE_LOC, SHAPE_REF, NULL);
  514. }
  515.  
  516. new_graf (indented)
  517.         bool    indented;
  518. {
  519.         prev_graf = 0;
  520.         if (mode == VMODE || head != tail)
  521.                 tail_append(new_param_glue(PAR_SKIP_CODE));
  522.         push_nest();
  523.         mode = HMODE;
  524.         space_factor = 1000;
  525.         if (indented) {
  526.                 tail = new_null_box();
  527.                 link(head) = tail;
  528.                 width(tail) = par_indent;
  529.         }
  530.         if (every_par != NULL)
  531.                 begin_token_list(every_par, EVERY_PAR_TEXT);
  532.         if (nest_ptr == 1) 
  533.                 build_page();
  534. }
  535.  
  536. indent_in_hmode ()
  537. {
  538.         ptr             p;
  539.         ptr             q;
  540.  
  541.         if (cur_chr > 0) {
  542.                 p = new_null_box();
  543.                 width(p) = par_indent;
  544.                 if (abs(mode) == HMODE)
  545.                         space_factor = 1000;
  546.                 else {
  547.                         q = new_noad();
  548.                         math_type(nucleus(q)) = SUB_BOX;
  549.                         info(nucleus(q)) = p;
  550.                         p = q;
  551.                 }
  552.                 tail_append(p);
  553.         }
  554. }
  555.  
  556. head_for_vmode ()
  557. {
  558.         if (mode < 0) {
  559.                 if (cur_cmd != HRULE)
  560.                         off_save();
  561.                 else {
  562.                         print_err("You can't use `");
  563.                         print_esc("hrule");
  564.                         print("' here except with leaders");
  565.                         help_head_for_vmode();
  566.                         error();
  567.                 }
  568.         } else {
  569.                 back_input();
  570.                 cur_tok = par_token;
  571.                 back_input();
  572.                 token_type = INSERTED;
  573.         }
  574. }
  575.         
  576. end_graf ()
  577. {
  578.         if (mode == HMODE) {
  579.                 if (head == tail)
  580.                         pop_nest();
  581.                 else
  582.                         line_break(widow_penalty);
  583.                 normal_paragraph();
  584.                 error_count = 0;
  585.         }
  586. }
  587.  
  588. append_to_vlist (b)
  589.         ptr             b;
  590. {
  591.         scal    d;
  592.         ptr             p;
  593.  
  594.         if (prev_depth > IGNORE_DEPTH) {
  595.                 d = width(baseline_skip) - prev_depth - height(b);
  596.                 if (d < line_skip_limit)
  597.                         p = new_param_glue(LINE_SKIP_CODE);
  598.                 else {
  599.                         p = new_skip_param(BASELINE_SKIP_CODE);
  600.                         width(temp_ptr) = d;
  601.                 }
  602.                 link(tail) = p;
  603.                 tail = p;
  604.         }
  605.         link(tail) = b;
  606.         tail = b;
  607.         prev_depth = depth(b);
  608. }
  609.  
  610. begin_insert_or_adjust ()
  611. {
  612.         if (cur_cmd == VADJUST)
  613.                 cur_val = 255;
  614.         else {
  615.                 scan_eight_bit_int();
  616.                 if (cur_val == 255) {
  617.                         print_err("You can't ");
  618.                         print_esc("insert");
  619.                         print_int(255);
  620.                         help_insert_255();
  621.                         error();
  622.                         cur_val = 0;
  623.                 }
  624.         }
  625.         saved(0) = cur_val;
  626.         incr(save_ptr);
  627.         new_save_level(INSERT_GROUP);
  628.         scan_left_brace();
  629.         normal_paragraph();
  630.         push_nest();
  631.         mode = -VMODE;
  632.         prev_depth = IGNORE_DEPTH;
  633. }
  634.  
  635. make_mark ()
  636. {
  637.         ptr             p;
  638.  
  639.         scan_toks(FALSE, TRUE);
  640.         p = get_node(SMALL_NODE_SIZE);
  641.         type(p) = MARK_NODE;
  642.         subtype(p) = 0;
  643.         mark_ptr(p) = def_ref;
  644.         link(tail) = p;
  645.         tail = p;
  646. }
  647.  
  648. append_penalty ()
  649. {
  650.         scan_int();
  651.         tail_append(new_penalty(cur_val));
  652.         if (mode == VMODE) 
  653.                 build_page();
  654. }
  655.  
  656. delete_last ()
  657. {
  658.         qword   m;
  659.         ptr             p;
  660.         ptr             q;
  661.  
  662.         if (mode == VMODE && tail == head) {
  663.                 if (cur_chr != GLUE_NODE || last_glue != MAX_HALFWORD) {
  664.                         you_cant();
  665.                         help_delete_last();
  666.                         if (cur_chr == KERN_NODE)
  667.                                 help_line[1] = "Try `I\\kern-\\lastkern' instead.";
  668.                         else if (cur_chr != GLUE_NODE)
  669.                                 help_line[1] = "Perhaps you can make the output routine do it.";
  670.                         error();
  671.                 }
  672.         } else if (!is_char_node(tail) && type(tail) == cur_chr) {
  673.                 q = head;
  674.                 do      {
  675.                         p = q;
  676.                         if (!is_char_node(q) && type(q) == DISC_NODE) {
  677.                                 for (m = 1; m <= replace_count(q); incr(m))
  678.                                         p = link(p);
  679.                                 if (p == tail)
  680.                                         return;
  681.                         }
  682.                         q = link(p);
  683.                 } while (q != tail);
  684.                 link(p) = NULL;
  685.                 flush_node_list(tail);
  686.                 tail = p;
  687.         }
  688. }
  689.  
  690. unpackage ()
  691. {       
  692.         int             c;
  693.         ptr             p;
  694.         
  695.         c = cur_chr;
  696.         scan_eight_bit_int();
  697.         p = box(cur_val);
  698.         if (p == NULL) return;
  699.         if (abs(mode) == MMODE ||
  700.                 abs(mode) == VMODE && type(p) != VLIST_NODE ||
  701.                 abs(mode) == HMODE && type(p) != HLIST_NODE) {
  702.                 print_err("Incompatible list can't be unboxed");
  703.                 help_pandora();
  704.                 error();
  705.                 return;
  706.         }
  707.         if (c == COPY_CODE)
  708.                 link(tail) = copy_node_list(list_ptr(p));
  709.         else {
  710.                 link(tail) = list_ptr(p);
  711.                 box(cur_val) = NULL;
  712.                 free_node(p, BOX_NODE_SIZE);
  713.         }
  714.         while (link(tail) != NULL)
  715.                 tail = link(tail);
  716. }
  717.  
  718. append_italic_correction ()
  719. {
  720.         ptr             p;
  721.         fnt             f;
  722.  
  723.         if (tail != head) {
  724.                 if (is_char_node(tail))
  725.                         p = tail;
  726.                 else if (type(tail) == LIGATURE_NODE)
  727.                         p = lig_char(tail);
  728.                 else return;
  729.         }
  730.         f = font(p);
  731.         tail_append(new_kern(char_italic(f, char_info(f, character(p)))));
  732.         subtype(tail) = EXPLICIT;
  733. }
  734.  
  735. append_discretionary ()
  736. {
  737.         int             c;
  738.  
  739.         tail_append(new_disc());
  740.         if (cur_chr == 1) {
  741.                 c = hyphen_char[cur_font];
  742.                 if (c >= 0 && c < 256)
  743.                         pre_break(tail) = new_character(cur_font, c);
  744.         } else {
  745.                 incr(save_ptr);
  746.                 saved(-1) = 0;
  747.                 scan_left_brace();
  748.                 new_save_level(DISC_GROUP);
  749.                 push_nest();
  750.                 mode = -HMODE;
  751.                 space_factor = 1000;
  752.         }
  753. }
  754.  
  755. build_discretionary ()
  756. {
  757.         int             n;
  758.         ptr             p;
  759.         ptr             q;
  760.  
  761.         unsave();
  762.         q = head;
  763.         p = link(q);
  764.         n = 0;
  765.         while (p != NULL) {
  766.                 if (!is_char_node(p) && type(p) > RULE_NODE &&
  767.                         type(p) != KERN_NODE && type(p) != LIGATURE_NODE) {
  768.                         print_err("Improper discretionary list");
  769.                         help_discretionary();
  770.                         error();
  771.                         begin_diagnostic();
  772.                         print_nl("The following discretionary sublist has been deleted:");
  773.                         show_box(p);
  774.                         end_diagnostic(TRUE);
  775.                         flush_node_list(p);
  776.                         link(q) = NULL;
  777.                         break;
  778.                 }
  779.                 q = p;
  780.                 p = link(q);
  781.                 incr(n);
  782.         }
  783.         p = link(head);
  784.         pop_nest();
  785.         switch ((int) saved(-1))
  786.         {
  787.         case 0:
  788.                 pre_break(tail) = p;
  789.                 break;
  790.  
  791.         case 1:
  792.                 post_break(tail) = p;
  793.                 break;
  794.  
  795.         case 2:
  796.                 if (n > 0 && abs(mode) == MMODE) {
  797.                         print_err("Illegal math ");
  798.                         print_esc("discretionary");
  799.                         help_math_disc();
  800.                         flush_node_list(p);
  801.                         n = 0;
  802.                         error();
  803.                 } else
  804.                         link(tail) = p;
  805.                 if (n <= MAX_QUARTERWORD)
  806.                         replace_count(tail) = n;
  807.                 else {
  808.                         print_err("Discretionary list is too long");
  809.                         help_disc();
  810.                         error();
  811.                 }
  812.                 if (n > 0) tail = q;
  813.                 decr(save_ptr);
  814.                 return;
  815.         }
  816.         incr(saved(-1));
  817.         scan_left_brace();
  818.         new_save_level(DISC_GROUP);
  819.         push_nest();
  820.         mode = -HMODE;
  821.         space_factor = 1000;
  822. }
  823.  
  824. make_accent ()
  825. {
  826.         scal    a;
  827.         fnt             f;
  828.         scal    h;
  829.         fourq   i;
  830.         ptr             p;
  831.         ptr             q;
  832.         ptr             r;
  833.         float   s;
  834.         float   t;
  835.         scal    w;
  836.         scal    x;
  837.         scal    delta;
  838.  
  839.         scan_char_num();
  840.         f = cur_font;
  841.         p = new_character(f, cur_val);
  842.         if (p != NULL) {
  843.                 x = x_height(f);
  844.                 s = (float) slant(f) / 65536.0;
  845.                 a = char_width(f, char_info(f, character(p)));
  846.                 do_assignments();
  847.                 q = NULL;
  848.                 f = cur_font;
  849.                 if (cur_cmd == LETTER ||
  850.                         cur_cmd == OTHER_CHAR ||
  851.                         cur_cmd ==  CHAR_GIVEN) 
  852.                         q = new_character(f, cur_chr);
  853.                 else if (cur_cmd ==  CHAR_NUM) {
  854.                         scan_char_num();
  855.                         q = new_character(f, cur_val);
  856.                 } else back_input();
  857.                 if (q != NULL) {
  858.                         t = (float) slant(f) / 65536.0;
  859.                         i = char_info(f, character(q));
  860.                         w = char_width(f, i); 
  861.                         h = char_height(f, height_depth(i));
  862.                         if (h != x) {
  863.                                 p = hpack(p, NATURAL);
  864.                                 shift_amount(p) = x - h;
  865.                         }
  866.                         delta = round((float) (w - a) / 2.0 + h * t - x * s);
  867.                         r = new_kern(delta);
  868.                         subtype(r) = ACC_KERN;
  869.                         link(tail) = r;
  870.                         link(r) = p;
  871.                         tail = new_kern(-a - delta);
  872.                         subtype(tail) = ACC_KERN;
  873.                         link(p) = tail; p = q;
  874.                 }
  875.                 link(tail) = p;
  876.                 tail = p;
  877.                 space_factor = 1000;
  878.         }
  879. }
  880.  
  881. align_error ()
  882. {
  883.         if (abs(align_state) > 2) {
  884.                 print_err("Misplaced ");
  885.                 print_cmd_chr(cur_cmd, cur_chr);
  886.                 if (cur_tok == TAB_TOKEN + '&') 
  887.                         help_tab();
  888.                 else help_align_error();
  889.                 error();
  890.         } else {
  891.                 back_input();
  892.                 if (align_state < 0) {
  893.                         print_err("Missing { inserted");
  894.                         incr(align_state);
  895.                         cur_tok = LEFT_BRACE_TOKEN + '{';
  896.                 } else {
  897.                         print_err("Missing } inserted");
  898.                         decr(align_state);
  899.                         cur_tok = RIGHT_BRACE_TOKEN + '}';
  900.                 }
  901.                 help_fix_alignment();
  902.                 ins_error();
  903.         }
  904. }
  905.  
  906. no_align_error ()
  907. {
  908.         print_err("Misplaced ");
  909.         print_esc("noalign");
  910.         help_noalign();
  911.         error();
  912. }
  913.  
  914. omit_error ()
  915. {
  916.         print_err("Misplaced ");
  917.         print_esc("omit");
  918.         help_omit();
  919.         error();
  920. }
  921.  
  922. do_endv ()
  923. {
  924.         if (cur_group == ALIGN_GROUP) {
  925.                 end_graf();
  926.                 if (fin_col())
  927.                         fin_row();
  928.         } else off_save();
  929. }
  930.  
  931. cs_error ()
  932. {
  933.         print_err("Extra ");
  934.         print_esc("endcsname");
  935.         help_csname();
  936.         error();
  937. }
  938.  
  939. /*
  940.  *      Help text
  941.  */
  942.  
  943.  
  944. help_head_for_vmode ()
  945. {
  946.         help2("To put a horizontal rule in an hbox or an alignment,",
  947.         "you should use \\leaders or \\hrulefill (see The TeXbook).");
  948. }
  949.  
  950.  
  951. help_close_group ()
  952. {
  953.         help2("You've closed more groups than you opened.",
  954.         "Such booboos are generally harmless, so keep going.");
  955. }
  956.  
  957.  
  958. help_output_balance ()
  959. {
  960.         help2("Your sneaky output routine has fewer real {'s than }'s.",
  961.         "I can't handle that very well; good luck.");
  962. }
  963.  
  964.  
  965. help_output ()
  966. {
  967.         help3("Your \\output commands should empty \\box255,",
  968.         "e.g., by saying `\\shipout\\box255'.",
  969.         "Proceed; I'll discard its present contents.");
  970. }
  971.  
  972.  
  973. help_group_close ()
  974. {
  975.         help5("I've deleted a group-closing symbol because it seems to be",
  976.         "spurious, as in `$x}$'. But perhaps the } is legitimate and",
  977.         "you forgot something else, as in `\\hbox{$x}'. In such cases",
  978.         "the way to recover is to insert both the forgotten and the",
  979.         "deleted material, e.g., by typing `I$}'.");
  980. }
  981.  
  982.  
  983. help_leaders ()
  984. {
  985.         help3("You should say `\\leaders <box or rule><hskip or vskip>'.",
  986.         "I found the <box or rule>, but there's no suitable",
  987.         "<hskip or vskip>, so I'm ignoring these leaders.");
  988. }
  989.  
  990.  
  991. help_lastbox_m ()
  992. {
  993.         help1("Sorry; this \\lastbox will be void.");
  994. }
  995.  
  996.  
  997. help_lastbox_v ()
  998. {
  999.         help2("Sorry...I usually can't take things from the current page.",
  1000.         "This \\lastbox will therefore be void.");
  1001. }
  1002.  
  1003.  
  1004. help_vsplit ()
  1005. {
  1006.         help2("I'm working on `\\vsplit<box number> to <dimen>';",
  1007.         "will look for the <dimen> next.");
  1008. }
  1009.  
  1010.  
  1011. help_box ()
  1012. {
  1013.         help3("I was expecting to see \\hbox or \\vbox or \\copy or \\box or",
  1014.         "something like that. So you might find something missing in",
  1015.         "your output. But keep trying; you can fix this later.");
  1016. }
  1017.  
  1018.  
  1019. help_insert_255 ()
  1020. {
  1021.         help1("I'm changing to \\insert0; box 255 is special.");
  1022. }
  1023.  
  1024.  
  1025. help_space_fac ()
  1026. {
  1027.         help1("I allow only values in the range 1..65536 here.");
  1028. }
  1029.  
  1030.  
  1031. help_delete_last ()
  1032. {
  1033.         help2("Sorry...I usually can't take things from the current page.",
  1034.         "Try `I\\vskip-\\lastskip' instead.");
  1035. }
  1036.  
  1037.  
  1038. help_pandora ()
  1039. {
  1040.         help3("Sorry, Pandora. (You sneaky devil.)",
  1041.         "I refuse to unbox an \\hbox in vertical mode or vice versa.",
  1042.         "And I can't open any boxes in math mode.");
  1043. }
  1044.  
  1045.  
  1046. help_math_disc ()
  1047. {
  1048.         help2("Sorry: The third part of a discretionary break must be",
  1049.         "empty, in math formulas. I had to delete your third part.");
  1050. }
  1051.  
  1052.  
  1053. help_discretionary ()
  1054. {
  1055.         help1("Discretionary lists must contain only boxes and kerns.");
  1056. }
  1057.  
  1058.  
  1059. help_disc ()
  1060. {
  1061.         help2("Wow---I never thought anybody would tweak me here.",
  1062.         "You can't seriously need such a huge discretionary list?");
  1063. }
  1064.  
  1065.  
  1066. help_missing_the ()
  1067. {
  1068.         help3("Please dont say \\count or \\dimen or \\skip in the midst of",
  1069.         "a paragraph or formula. I'm going to assume that you",
  1070.         "meant to say `\\the\\count' or `\\the\\dimen' or `\\the\\skip',");
  1071. }
  1072.  
  1073.  
  1074. help_tab ()
  1075. {
  1076.         help6("I can't figure out why you would want to use a tab mark",
  1077.         "here. If you want an ampersand, the remedy is",
  1078.         "simple: Just type `I\\&' now. But if some right brace",
  1079.         "up above has ended a previous alignment prematurely,",
  1080.         "you're probably due for more error messages, and you",
  1081.         "might try typing `S' now just to see what is salvageable.");
  1082. }
  1083.  
  1084.  
  1085. help_align_error ()
  1086. {
  1087.         help5("I can't figure out why you would want to use a tab mark",
  1088.         "or \\cr or \\span just now. If something like a right brace",
  1089.         "up above has ended a previous alignment prematurely,",
  1090.         "you're probably due for more error messages, and you",
  1091.         "might try typing `S' now just to see what is salvageable.");
  1092. }
  1093.  
  1094.  
  1095. help_align_cr ()
  1096. {
  1097.         help1("I'm guessing that you meant to end an alignment here.");
  1098. }
  1099.         
  1100.  
  1101. help_fix_alignment ()
  1102. {
  1103.         help3("I've put in what seems to be necessary to fix",
  1104.         "the current column of the current alignment.",
  1105.         "Try to go on, since this might almost work.");
  1106. }
  1107.  
  1108.  
  1109. help_noalign ()
  1110. {
  1111.         help2("I expect to see \\noalign only after the \\cr of",
  1112.         "an alignment. Proceed, and I'll ignore this case.");
  1113. }
  1114.  
  1115.  
  1116. help_omit ()
  1117. {
  1118.         help2("I expect to see \\omit only after tab marks or the \\cr of",
  1119.         "an alignment. Proceed, and I'll ignore this case.");
  1120. }
  1121.  
  1122.  
  1123. help_csname ()
  1124. {
  1125.         help1("I'm ignoring this, since I wasn't doing a \\csname.");
  1126. }
  1127.